#if 0
#include "hello_world_main.h"
#include "zhi_xing.h"
#include "gatts_table_creat_demo.h" //ble蓝牙

#include "socket.h"

static const char *TAG = "ZHI_XING: ";
static TaskHandle_t juBing;

void task_socket(void *pvParameter)
{
    if (init_sockets())
    {
        sockets_faSong("hfdkhfskhfksdjfhjkd");
        while (1)
        {
            sockets_jieShou();
            vTaskDelay(200 / portTICK_PERIOD_MS);
        }
    }
    ESP_LOGI(TAG, "task_socket xian chen tui chu\n");
}

void task_function(void *pvParameter)
{
    uint8_t ucRxData[HUAN_CHONG_QU_LEN];
    size_t xReceivedBytes;
    const TickType_t xBlockTime = pdMS_TO_TICKS(20);
    float zkbGaiBian = 0;
    TickType_t yanShiJI = 0;
    bool qiTingJB = false;
    while (1)
    {
        // 接收消息
        // 从消息缓冲区接收下一条消息。在阻塞状态下等待（因此不使用任何 CPU 处理时间）最多 100 毫秒，消息才可用。
        xReceivedBytes = xMessageBufferReceive(socketBufferQ,
                                               (void *)ucRxData,
                                               HUAN_CHONG_QU_LEN,
                                               xBlockTime);
        if (xReceivedBytes > 0)
        {
            //ucRxData[xReceivedBytes + 1] = '\0'; //?
            printf(" jie-shou1: ucRxData is %d long. ucRxData : %s \n", xReceivedBytes, ucRxData);
            char leiXinJ = ucRxData[0];
            char zkbJieShou = ucRxData[1];
            if (leiXinJ == 'x')
            {
                switch (zkbJieShou)
                {
                case 'a': // WIFI连接
                    printf("--------------OK---------------\r\n");
                    vTaskDelay(1000 / portTICK_PERIOD_MS);
                    xTaskCreate(task_socket, "task_socket", 1024 * 3, NULL, 12, juBing);

                    break;
                case 'b': // WIFI断开
                    printf("--------------no OK---------------\n\r");
                    close_sockets();
                    vTaskDelete(juBing);
                    break;
                default:
                    break;
                }
            }
        }
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

// 多线程,从队列接收的任务。
void vADifferentTask(void *pvParameters)
{ // vTaskDelete(NULL)可以用于删除任务自身。
    uint8_t ucRxData[16];
    size_t xReceivedBytes;
    const TickType_t xBlockTime = pdMS_TO_TICKS(20);
    float zkbGaiBian = 0;
    TickType_t yanShiJI = 0;
    bool qiTingJB = false;
    while (1)
    {
        // 接收消息
        // 从消息缓冲区接收下一条消息。在阻塞状态下等待（因此不使用任何 CPU 处理时间）最多 100 毫秒，消息才可用。
        xReceivedBytes = xMessageBufferReceive(xMessageBuffer,
                                               (void *)ucRxData,
                                               sizeof(ucRxData),
                                               xBlockTime);

        if (xReceivedBytes > 0)
        {

            printf(" jie-----shou: ucRxData is %d long. ucRxData : %s \n", xReceivedBytes, ucRxData);
            char leiXinJ = ucRxData[0];
            char zkbJieShou = ucRxData[1];
            if (leiXinJ == 'z')
            {
                switch (zkbJieShou)
                {
                case 'q':
                    zkbGaiBian = 0.5;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    qiTingJB = true;
                    yanShiJI = 0;
                    break;
                case 'a':
                    zkbGaiBian = 0.2;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 'b':
                    zkbGaiBian = 0.4;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 'c':
                    zkbGaiBian = 0.6;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 'd':
                    zkbGaiBian = 0.8;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 'e':
                    zkbGaiBian = 0.98;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 't':
                    zkbGaiBian = 0;
                    yanShiJI = 0;
                    qiTingJB = false;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                default:
                    break;
                }
            }
        }
        if (qiTingJB)
        {
            yanShiJI++;
            if (yanShiJI > 10 * 5)
            {
                zkbGaiBian = 0;
                yanShiJI = 0;
                qiTingJB = false;
                ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
            }
        }

        ledPwmTianYao(zkbGaiBian);
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

#elif 1

#include "c3_main.h"
#include "zhi_xing.h"
#include "gatts_table_creat_demo.h" //ble蓝牙

#include "socket.h"
#include "wifi.h" //WIFI

#define MING_MING_KONG_JIA_1 "wangLuo"

static const char *TAG = "ZHI_XING: ";
static TaskHandle_t juBing;
void task_socket_1(void *pvParameter)
{
    uint16_t shijain = 0;
    char ip[16] = {0};
    nvs_du_qu_value_all("wacl\\wangLuo\\ip", ip);
    while (1)
    {
        if (init_sockets(8080, ip)) // 连接sockets服务器
        {
            sockets_faSong("esp32-c3:ok"); // 发送消息到sockets服务器
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            while (1)
            {
                sockets_jieShou(); // 接收sockets服务器的消息
                vTaskDelay(200 / portTICK_PERIOD_MS);
                shijain++;
                if (shijain > 5 * 300) // 300秒
                {
                    shijain = 0;
                    sockets_faSong("esp32-c3:ok"); // 发送心跳消息到sockets服务器
                }
            }
        }
        vTaskDelay(5000 / portTICK_PERIOD_MS);
        ESP_LOGI(TAG, "socket 连接失败!\n");
    }
}

void task_function(void *pvParameter)
{
    uint8_t ucRxData[XI_TONG_HUAN_CHONG_QU_LEN];
    size_t xReceivedBytes;
    const TickType_t xBlockTime = pdMS_TO_TICKS(20);
    float zkbGaiBian = 0;
    TickType_t yanShiJI = 0;
    bool wifiQiTing = false;
    while (1)
    {
        // 接收消息
        // 从消息缓冲区接收下一条消息。在阻塞状态下等待（因此不使用任何 CPU 处理时间）最多 100 毫秒，消息才可用。
        xReceivedBytes = xMessageBufferReceive(socketBufferQ,
                                               (void *)ucRxData,
                                               XI_TONG_HUAN_CHONG_QU_LEN,
                                               xBlockTime);
        if (xReceivedBytes > 0)
        {
            // ucRxData[xReceivedBytes + 1] = '\0'; //?
            printf(" jie-shou1: ucRxData is %d long. ucRxData : %s \n", xReceivedBytes, ucRxData);
            char leiXinJ = ucRxData[0];
            char caoZuo = ucRxData[1];
            if (leiXinJ == 'x')
            {
                switch (caoZuo)
                {
                case 'a': // WIFI连接
                    ESP_LOGI(TAG, "*-OK----jian li task_socket_1 xian chen---------*\n");
                    vTaskDelay(1000 / portTICK_PERIOD_MS);
                    xTaskCreate(task_socket_1, "task_socket_1", 1024 * 3, NULL, 12, &juBing);

                    break;
                case 'b': // WIFI断开
                    ESP_LOGI(TAG, "*-NO----zhu xiao task_socket_1 xian chen---------*\n");
                    close_sockets();
                    vTaskDelete(juBing);
                    break;
                case 'c': // 关闭蓝牙
                    ESP_ERROR_CHECK(esp_bt_controller_disable());
                    break;
                default:
                    break;
                }
            }
            else if (leiXinJ == 'w')
            {
                switch (caoZuo)
                {
                case 'a': // 保存WIFI信息
                    if (wifi_set("wwcccxxx\\chenxin1234567890"))
                    {
                        esp_restart(); // 重启
                    }
                    break;
                case 'b': // 保存socket连接信息
                    if (ESP_OK == nvs_tian_jia_value_all("wacl\\wangLuo\\ip\\192.168.1.12"))
                    {
                        vTaskDelay(2000 / portTICK_PERIOD_MS);
                        esp_restart(); // 重启
                    }
                    ESP_LOGI(TAG, "socket 信息写入失败!\n");
                    break;
                case 'c':                                         // 保存WIFI信息
                    if (nvs_tian_jia_value_all((char *)ucRxData)) //"wwcccxxx/chenxin1234567890"
                    {
                        vTaskDelay(2000 / portTICK_PERIOD_MS);
                    }
                    break;
                case 'z':          // 保存WIFI信息
                    esp_restart(); // 重启
                    break;
                default:
                    break;
                }
            }
        }
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

// 多线程,从队列接收的任务。
void vADifferentTask(void *pvParameters)
{ // vTaskDelete(NULL)可以用于删除任务自身。
    uint8_t ucRxData[HUAN_CHONG_QU_LEN];
    size_t xReceivedBytes;
    const TickType_t xBlockTime = pdMS_TO_TICKS(20);
    float zkbGaiBian = 0;
    //TickType_t yanShiJI = 0;//0-4294967295
    uint16_t yanShiJI = 0;//0-65535
    bool qiTingJB = false;
    while (1)
    {
        // 接收消息
        // 从消息缓冲区接收下一条消息。在阻塞状态下等待（因此不使用任何 CPU 处理时间）最多 100 毫秒，消息才可用。
        xReceivedBytes = xMessageBufferReceive(xMessageBuffer,
                                               (void *)ucRxData,
                                               sizeof(ucRxData),
                                               xBlockTime);

        if (xReceivedBytes > 0)
        {

            printf(" jie-----shou: ucRxData is %d long. ucRxData : %s \n", xReceivedBytes, ucRxData);
            char leiXinJ = ucRxData[0];
            char zkbJieShou = ucRxData[1];
            if (leiXinJ == 'z')
            {
                switch (zkbJieShou)
                {
                case 'q':
                    zkbGaiBian = 0.5;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    qiTingJB = true;
                    yanShiJI = 0;
                    break;
                case 'a':
                    zkbGaiBian = 0.2;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 'b':
                    zkbGaiBian = 0.4;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 'c':
                    zkbGaiBian = 0.6;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 'd':
                    zkbGaiBian = 0.8;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 'e':
                    zkbGaiBian = 0.98;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 't':
                    zkbGaiBian = 0;
                    yanShiJI = 0;
                    qiTingJB = false;
                    ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
                    break;
                case 'f': // 写

                    break;
                case 'g':
                    nvs_erase();
                    break;
                case 'h':
                    // 无此数据 ESP_ERR_NVS_NOT_FOUND
                    delete_wifi_credentials();
                    break;
                case 'i':
                    break;
                case 'j':
                    u_int16_t ds = 8506;
                    if (ESP_OK == nvs_tian_jia_value("asd", "zxc", &ds, 1))
                    {
                        ESP_LOGI(TAG, "保存成功!\n");
                    }
                    break;
                case 'k':
                    u_int16_t dss = 0;
                    if (ESP_OK == nvs_du_qu_value("asd", "zxc", &dss, 1))
                    {
                        ESP_LOGI(TAG, "读取成功 dss = %d!\n", dss);
                    }
                    break;
                case 'l':

                    break;
                case 'm':

                    break;
                case 'n':

                    break;
                case 'o':

                    break;
                default:
                    break;
                }
            }
        }
        if (qiTingJB)
        {
            yanShiJI++;
            if (yanShiJI > 10 * 60)
            {
                zkbGaiBian = 0;
                yanShiJI = 0;
                qiTingJB = false;
                ESP_LOGI(TAG, "现在的占空比为: %f", zkbGaiBian);
            }
        }
        ledPwmTianYao(zkbGaiBian);
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

/******************掉电保存**********************/
bool wifi_set(const char *data)
{
    esp_err_t err;
    char ssid[WIFI_SSID_LEN] = {0};
    char pass[WIFI_PASS_LEN] = {0};
    size_t i = 0;
    // char* dd = "wwcccxxx\\chenxin1234567890";
    size_t len = strlen(data); // 计算字符串长度,不含结尾的'\0'
    if (len < 10)              // 头部2位+1分隔符+密码6位+1位ssid
    {
        return false;
    }
    // printf("len = %zu\n",len);
    for (; i < len; i++)
    {
        ssid[i] = data[i + 2]; //+2是因为前面2个数据是类型数据
        // printf("ssid = %c , i = %d\n", ssid[i], i);
        if (ssid[i] == '\\')
        {
            break;
        }
    }
    ssid[i] = '\0';
    ESP_LOGI(TAG, "ssid = %s\n", (char *)ssid);
    err = nvs_tian_jia_str(MING_MING_KONG_JIA_1, "wi_fi", ssid);
    if (err != ESP_OK)
    {
        printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
        return false;
    }
    size_t ii = 0;
    for (i += 3; i < len; i++) //+3是因为前面2个数据是类型数据+1个'/'分割符
    {
        pass[ii] = data[i];
        // printf("pass = %c , i = %d\n", pass[ii], i);
        ii++;
    }
    pass[ii + 1] = '\0';
    ESP_LOGI(TAG, "pass = %s\n", (char *)pass);
    err = nvs_tian_jia_str(MING_MING_KONG_JIA_1, "pass", pass);
    if (err != ESP_OK)
    {
        printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
        return false;
    }
    return true;
}

bool wifi_Start()
{
    char ssid[WIFI_SSID_LEN] = {0};
    char pass[WIFI_PASS_LEN] = {0};
    esp_err_t err;
    err = nvs_du_qu_str(MING_MING_KONG_JIA_1, "wi_fi", ssid);
    if (err != ESP_OK)
    {
        printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
        return false;
    }
    err = nvs_du_qu_str(MING_MING_KONG_JIA_1, "pass", pass);
    if (err != ESP_OK)
    {
        printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
        return false;
    }
    wifi_init(ssid, pass);
    return true;
}

esp_err_t nvs_du_qu_str(const char *mingMingKongJIanI8P, const char *key, char *strSZP)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    size_t len = 0;
    // Open
    err = nvs_open(mingMingKongJIanI8P, // 命名空间名称
                   NVS_READWRITE,       // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);         // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        ESP_LOGI(TAG, "err ==  1\n");
        return err;
    }
    /*这些函数根据键的名称检索键的值*/
    err = nvs_get_str(my_handle, key, NULL, &len); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回,包含'\0'。
    if (err != ESP_OK)
    {
        ESP_LOGI(TAG, "err ==  2\n");
        return err;
    }
    char *run_time = malloc(len);                      // malloc 动态分配内存
    err = nvs_get_str(my_handle, key, run_time, &len); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
    if (err != ESP_OK)
    {
        ESP_LOGI(TAG, "err ==  3\n");
        free(run_time);
        return err;
    }
    // ESP_LOGI(TAG, "run_time ==  %s\n", run_time);
    for (size_t i = 0; i < len; i++)
    {
        strSZP[i] = run_time[i];
    }
    // ESP_LOGI(TAG, "strSZP ==  %s\n", strSZP);

    free(run_time); // 释放分配的动态内存

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}

esp_err_t nvs_du_qu_value(const char *mingMingKongJIanI8P, const char *key, void *value, uint8_t lx)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    // Open
    err = nvs_open(mingMingKongJIanI8P, // 命名空间名称
                   NVS_READWRITE,       // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);         // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        ESP_LOGI(TAG, "Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
        return err;
    }

    if (lx == 1)
    {
        uint16_t valuels = 0;
        /*这些函数根据键的名称检索键的值*/
        err = nvs_get_u16(my_handle, key, &valuels); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回,包含'\0'。
        if (err != ESP_OK)
        {
            return err;
        }
        *(u_int16_t *)value = valuels;
    }
    else if (lx == 2)
    {
        uint32_t valuels = 0;
        /*这些函数根据键的名称检索键的值*/
        err = nvs_get_u32(my_handle, key, &valuels); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回,包含'\0'。
        if (err != ESP_OK)
        {
            return err;
        }
        *(u_int32_t *)value = valuels;
    }

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}
esp_err_t nvs_du_qu_value_all(const char *data, void *value)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    // const char *data = "wdxl\\mingming\\abcdefghig"; // wdxl \\min gmin g\\ab cdef  ghig  \\564  82
    size_t len = strlen(data); // 计算字符串长度,不含结尾的'\0'

    char mingMingKongJIanI8P[HUAN_CHONG_QU_LEN] = {0};
    char key[HUAN_CHONG_QU_LEN] = {0};
    char zhi[HUAN_CHONG_QU_LEN] = {0};
    u_int16_t i = 0;
    u_int16_t ii = 5;
    for (; ii < len; ii++)
    {
        mingMingKongJIanI8P[i] = data[ii];
        // printf("mmkj = %c , i = %d, ii = %d\n", mingMingKongJIanI8P[i], i, ii);
        if (mingMingKongJIanI8P[i] == '\\' || i >= 14)
        {
            break;
        }
        i++;
    }
    mingMingKongJIanI8P[i] = '\0';
    // printf("%s\n", mingMingKongJIanI8P);
    ii++;
    i = 0;
    for (; ii < len; ii++)
    {
        key[i] = data[ii];
        // printf("key = %c , i = %d, ii = %d\n", key[i], i, ii);
        i++;
    }
    key[i] = '\0';
    // printf("%s\n", key);

    // Open
    err = nvs_open(mingMingKongJIanI8P, // 命名空间名称
                   NVS_READWRITE,       // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);         // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        ESP_LOGI(TAG, "Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
        return err;
    }
    switch (data[2])
    {
    case 'a':
        uint16_t valuelsU16 = 0;
        /*这些函数根据键的名称检索键的值*/
        err = nvs_get_u16(my_handle, key, &valuelsU16); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回,包含'\0'。
        if (err != ESP_OK)
        {
            return err;
        }
        *(u_int16_t *)value = valuelsU16;
        nvs_close(my_handle);
        return ESP_OK;
    case 'b':
        uint32_t valuelsU32 = 0;
        /*这些函数根据键的名称检索键的值*/
        err = nvs_get_u32(my_handle, key, &valuelsU32); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回,包含'\0'。
        if (err != ESP_OK)
        {
            return err;
        }
        *(u_int32_t *)value = valuelsU32;
        nvs_close(my_handle);
        return ESP_OK;
    case 'c':
        /*这些函数根据键的名称检索键的值*/
        err = nvs_get_str(my_handle, key, NULL, &len); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回,包含'\0'。
        if (err != ESP_OK)
        {
            ESP_LOGI(TAG, "err ==  5\n");
            return err;
        }
        char *run_time = malloc(len);                      // malloc 动态分配内存
        err = nvs_get_str(my_handle, key, run_time, &len); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
        if (err != ESP_OK)
        {
            ESP_LOGI(TAG, "err ==  6\n");
            free(run_time);
            return err;
        }
        // ESP_LOGI(TAG, "run_time ==  %s\n", run_time);
        memcpy(value, run_time, len);
        // ESP_LOGI(TAG, "strSZP ==  %s\n", strSZP);

        free(run_time); // 释放分配的动态内存
        nvs_close(my_handle);
        return ESP_OK;
    default:
        break;
    }

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_FAIL;
}

esp_err_t nvs_tian_jia_str(const char *mingMingKongJIanI8P, const char *key, const char *str)
{
    nvs_handle_t my_handle;
    esp_err_t err;

    // Open
    err = nvs_open(mingMingKongJIanI8P, // 命名空间名称
                   NVS_READWRITE,       // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);         // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        return err;
    }
    err = nvs_set_str(my_handle, key, str); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
    {
        return err;
    }
    //  承诺书面价值。设置任何值后，必须调用 nvs_commit() 以确保更改写入闪存。
    //  实现可能会在其他时间写入存储，但这不能保证。
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        return err;
    }

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}

esp_err_t nvs_tian_jia_value(const char *mingMingKongJIanI8P, const char *key, void *value, uint8_t lx)
{
    nvs_handle_t my_handle;
    esp_err_t err;

    // Open
    err = nvs_open(mingMingKongJIanI8P, // 命名空间名称
                   NVS_READWRITE,       // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);         // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        return err;
    }
    if (lx == 1)
    {
        uint16_t data = *(u_int16_t *)value;
        printf("nvs  data =%d \n", data);
        err = nvs_set_u16(my_handle, key, data); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
        {
            return err;
        }
    }
    else if (lx == 2)
    {
        uint32_t data = *(u_int32_t *)value;
        err = nvs_set_u32(my_handle, key, data); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
        {
            return err;
        }
    }

    //  承诺书面价值。设置任何值后，必须调用 nvs_commit() 以确保更改写入闪存。
    //  实现可能会在其他时间写入存储，但这不能保证。
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        return err;
    }

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_OK;
}
esp_err_t nvs_tian_jia_value_all(const char *data)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    // const char *data = "wacl\\wangLuo\\192.168.1.12"
    size_t len = strlen(data); // 计算字符串长度,不含结尾的'\0'

    char mingMingKongJIanI8P[HUAN_CHONG_QU_LEN] = {0};
    char key[HUAN_CHONG_QU_LEN] = {0};
    char zhi[HUAN_CHONG_QU_LEN] = {0};
    uint16_t i = 0;
    uint16_t ii = 5;
    for (; ii < len; ii++)
    {
        mingMingKongJIanI8P[i] = data[ii];
        // printf("mmkj = %c , i = %d, ii = %d\n", mingMingKongJIanI8P[i], i, ii);
        if (mingMingKongJIanI8P[i] == '\\' || i >= 14)
        {
            break;
        }
        i++;
    }
    mingMingKongJIanI8P[i] = '\0';
    // printf("%s\n", mingMingKongJIanI8P);
    ii++;
    i = 0;
    for (; ii < len; ii++)
    {
        key[i] = data[ii];
        // printf("key = %c , i = %d, ii = %d\n", key[i], i, ii);
        if (key[i] == '\\')
        {
            break;
        }
        i++;
    }
    key[i] = '\0';
    // printf("%s\n", key);
    ii++;
    i = 0;
    if (data[2] == 'c')
    {
        for (; ii < len; ii++)
        {
            zhi[i] = data[ii];
            // printf("zhi = %c , i = %d, ii = %d\n", zhi[i], i, ii);
            i++;
        }
        zhi[i] = '\0';
    }
    else
    {
        for (; ii < len; ii++)
        {
            zhi[i] = data[ii];
            // printf("zhi = %c , i = %d, ii = %d\n", zhi[i], i, ii);
            i++;
        }
    }

    // uint32_t sa = atoi(zhi);

    // Open
    err = nvs_open(mingMingKongJIanI8P, // 命名空间名称
                   NVS_READWRITE,       // NVS_READWRITE 或 NVS_READONLY。如果 NVS_READONLY，将打开一个只读句柄。
                   &my_handle);         // 如果成功（返回代码为零），句柄将在此参数中返回。
    if (err != ESP_OK)
    {
        return err;
    }
    switch (data[2])
    {
    case 'a':
        uint16_t dataU16 = atoi(zhi);
        err = nvs_set_u16(my_handle, key, dataU16); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
        {
            return err;
        }
        // 设置任何值后，必须调用 nvs_commit() 以确保更改写入闪存。
        err = nvs_commit(my_handle);
        if (err != ESP_OK)
        {
            return err;
        }
        nvs_close(my_handle);
        return ESP_OK;
    case 'b':
        uint32_t dataU32 = atoi(zhi);
        err = nvs_set_u32(my_handle, key, dataU32); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
        {
            return err;
        }
        // 设置任何值后，必须调用 nvs_commit() 以确保更改写入闪存。
        //  实现可能会在其他时间写入存储，但这不能保证
        err = nvs_commit(my_handle);
        if (err != ESP_OK)
        {
            return err;
        }
        nvs_close(my_handle);
        return ESP_OK;
    case 'c':
        err = nvs_set_str(my_handle, key, zhi); // 指向输出值的指针。nvs_get_str 和 nvs_get_blob 可能为 NULL，在这种情况下，所需的长度将在长度参数中返回。
        if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
        {
            return err;
        }
        // 设置任何值后，必须调用 nvs_commit() 以确保更改写入闪存。
        //  实现可能会在其他时间写入存储，但这不能保证
        err = nvs_commit(my_handle);
        if (err != ESP_OK)
        {
            return err;
        }
        nvs_close(my_handle);
        return ESP_OK;
    default:
        break;
    }

    // 关闭存储句柄并释放所有分配的资源
    nvs_close(my_handle);
    return ESP_FAIL;
}

void nvs_init()
{
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        // NVS分区被截断，需要擦除重试nvs_flash_init
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);
}

void nvs_erase()
{
    esp_err_t err;
    // NVS分区被截断，需要擦除重试nvs_flash_init
    err = nvs_flash_erase();
    if (err != ESP_OK)
    {
        printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));
    }
    err = nvs_flash_init();
    ESP_ERROR_CHECK(err);
}

void delete_wifi_credentials()
{
    nvs_handle my_handle;
    esp_err_t err;
    // 打开NVS分区
    err = nvs_open("storage", NVS_READWRITE, &my_handle);
    if (err != ESP_OK)
    {
        // 处理打开NVS分区失败的情况
        return;
    }
    // 删除Wi-Fi SSID和密码的键值对
    err = nvs_erase_key(my_handle, "wifi_ssid");
    if (err != ESP_OK)
    {
        // 处理删除SSID键值对失败的情况
    }
    err = nvs_erase_key(my_handle, "wifi_password");
    if (err != ESP_OK)
    {
        // 处理删除密码键值对失败的情况
    }
    err = nvs_commit(my_handle);
    // 关闭NVS分区
    nvs_close(my_handle);
}

bool nvs_shan_chu_all(const char *mingMingKongJIanI8P)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    err = nvs_erase_all(mingMingKongJIanI8P);
    if (ESP_OK != err)
    {
        return false;
    }
    return true;
}

bool nvs_shan_chu_key(const char *mingMingKongJIanI8P, const char *key)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    err = nvs_erase_key(mingMingKongJIanI8P, key);
    if (ESP_OK != err)
    {
        return false;
    }
    return true;
}









#endif